package com.monochromebytes.mononet.packet;

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;

/**
 * The abstract base class of incoming and outgoing UDP packets.
 * 
 * Every Packet holds a ByteBuffer containing the data of the packet and an
 * InetSocketAddress of its sender and recipient.
 * 
 * @author ted
 */
public abstract class Packet {

    /**
     * The maximum size of the data that can be transfered by an UDP packet.
     */
    public final static int         MAX_LENGTH = 65507;

    /**
     * The buffer that stores the data of the packet.
     * 
     * The position of the data is set to 0 and the capacity as well as the
     * limit is set to the size of the packet data.
     */
    private final ByteBuffer        data;

    /**
     * The socket address (UDP port and IP address) of the sender of this
     * packet.
     */
    private final InetSocketAddress sender;

    /**
     * The socket address (UDP port and IP address) of the recipient of this
     * packet.
     */
    private final InetSocketAddress recipient;

    /**
     * Creates a new Packet with the given length, its sender and
     * recipient.
     * 
     * A new indirect ByteBuffer will be allocated with the given length.
     * 
     * @param length
     *            The length of the buffer storing the data of the Packet.
     * @param sender
     *            The sender of this Packet.
     * @param recipient
     *            The recipient of this Packet.
     */
    public Packet(int length, InetSocketAddress sender, InetSocketAddress recipient) {
        assert(length < Packet.MAX_LENGTH); // TODO
        this.data = ByteBuffer.allocate(length);
        this.recipient = recipient;
        this.sender = sender;
    }

    public void putData(ByteBuffer data) {
        this.data.put(data);
        this.data.clear();
    }

    /**
     * Returns a copy of the ByteBuffer the data of this Packet is stored in.
     * 
     * @return A copy of the ByteBuffer the data of this Packet is stored in.
     */
    public ByteBuffer getData() {
        return this.data.duplicate();
    }

    /**
     * Returns the length of the data of this Packet.
     * 
     * The length is specified as the remaining data of the Packets buffer.
     * 
     * @see buffer
     * @return The length of the data of this Packet.
     */
    public int getLength() {
        return this.data.remaining();
    }

    /**
     * Returns the socket address (UDP port and IP address) of the recipient of
     * this Packet.
     * 
     * @return The socket address (UDP port and IP address) of the recipient of
     *         this Packet.
     */
    public InetSocketAddress getRecipient() {
        return this.recipient;
    }

    /**
     * Returns InetSocketAddress (UDP port and IP address) of the sender of this
     * Packet.
     * 
     * @return InetSocketAddress (UDP port and IP address) of the sender of this
     *         Packet.
     */
    public InetSocketAddress getSender() {
        return this.sender;
    }
}
